<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  概念
  策略模式的定义是:定义一系列的算法，把它们一个个封装起来，并且使它们可以相互替换。
  
  策略模式指的是定义一系列的算法，把它们一个个封装起来。将不变的部分和变化的部分隔开是每个设计模式的主题，策略模式也不例外，策略模式的目的就是将算法的使用与算法的实现分离开来。
  
  一个基于策略模式的程序至少由两部分组成。第一个部分是一组策略类，策略类封装了具体 的算法，并负责具体的计算过程。 第二个部分是环境类Context，Context 接受客户的请求，随后 把请求委托给某一个策略类。要做到这点，说明 Context中要维持对某个策略对象的引用。
  
  策略模式的实现并不复杂，关键是如何从策略模式的实现背后，找到封装变化、委托和多态性这些思想的价值。
  
  场景
  从定义上看，策略模式就是用来封装算法的。但如果把策略模式仅仅用来封装算法，未免有一点大材小用。在实际开发中，我们通常会把算法的含义扩散开来，使策略模式也可以用来封装 一系列的“业务规则”。只要这些业务规则指向的目标一致，并且可以被替换使用，我们就可以 用策略模式来封装它们。
  
  优缺点
  优点
  策略模式利用组合、委托和多态等技术和思想，可以有效地避免多重条件选择语句。
  策略模式提供了对开放—封闭原则的完美支持，将算法封装在独立的strategy中，使得它们易于切换，易于理解，易于扩展。
  策略模式中的算法也可以复用在系统的其他地方，从而避免许多重复的复制粘贴工作。
  在策略模式中利用组合和委托来让 Context 拥有执行算法的能力，这也是继承的一种更轻便的替代方案。
  缺点
  增加许多策略类或者策略对象，但实际上这比把它们负责的 逻辑堆砌在 Context 中要好。
  要使用策略模式，必须了解所有的 strategy，必须了解各个 strategy 之间的不同点， 这样才能选择一个合适的 strategy。
  但这些缺点并不严重
  <script>
    // 绩效为 S 的人   年终奖为 4 倍工资
    // A 3倍   B 2倍
    // var calculate = function (level, salary) {
    //   if (level === 'S') {
    //     return salary * 4
    //   }
    //   if (level === 'A') {
    //     return salary * 3
    //   }
    //   if (level === 'B') {
    //     return salary * 2
    //   }
    // }
    // console.log(calculate('S', 20000))

    // var pS = function () {}
    // pS.prototype.calculate = function (salary) {
    //   return salary * 4
    // }
    // var pA = function () {}
    // pA.prototype.calculate = function (salary) {
    //   return salary * 3
    // }
    // var pB = function () {}
    // pB.prototype.calculate = function (salary) {
    //   return salary * 2
    // }
    // var Bouns = function () {
    //   this.salary = null
    //   this.strategy = null
    // }
    // Bouns.prototype.setSalary = function (salary) {
    //   this.salary = salary
    // }
    // Bouns.prototype.setStrategy = function (strategy) {
    //   this.strategy = strategy
    // }
    // Bouns.prototype.getBouns = function () {
    //   return this.strategy.calculate(this.salary)
    // }
    // var bouns = new Bouns()
    // bouns.setSalary(20000)
    // bouns.setStrategy(new pS)
    // console.log(bouns.getBouns())

    // 函数也是对象 js自身的特性导致
    var getStrategies = {
      'S': function (salary) {
        return salary * 4
      },
      'A': function (salary) {
        return salary * 3
      },
      'B': function (salary) {
        return salary * 2
      }
    }
    var getBouns = function (level, salary) {
      return getStrategies[level](salary)
    }
    console.log(getBouns('S', 20000))
  </script>
</body>
</html>